/*
 * Created on Dec 18, 2007
 */
package com.mgmaps.utils;


/**
 * Thread for operations that need to be asynchronous. Instead of creating a thread
 * for each such operation, we have a single thread that performs those operations in
 * sequence, but asynchronous relative to the main flow of the app.
 *
 * @author CristiS
 * @version 1.0
 */
public class AsyncCalls extends Thread {
  private boolean quitting;
  private final ExtQueue q;
  
  public static AsyncCalls instance = new AsyncCalls();
  
  public AsyncCalls() {
    q = new ExtQueue();
  }
  
  /**
   * Main method.
   * 
   * @see java.lang.Thread#run()
   */
  public void run() {
    Runnable obj = null;
    
    while(!isQuitting()) {
      synchronized(this) {
        // is queue empty?
        if (q.isEmpty())
          try {
            wait();
          }
          catch (InterruptedException ie) {
          }
          
        // consume one element
        obj = (Runnable) q.pop();
      }
      
      if (isQuitting())
        break;
      
      // call the run method
      if (obj != null)
        obj.run();
    }
  }
  
  /**
   * Synchronized getter for quitting.
   * 
   * @return quitting
   */
  private synchronized boolean isQuitting() {
    return quitting;
  }
  
  /**
   * Set the quitting flag.
   */
  public synchronized void notifyExit() {
    quitting = true;
    notify();
  }

  /**
   * Call a run method in the thread.
   * 
   * @param o IRunnable object
   */
  public synchronized void setRunnable(Runnable o) {
    q.push(o);
    notify();
  }
}
